package com.polidea.rxohosble2.internal.scan;

import bleshadow.javax.inject.Inject;
import com.polidea.rxohosble2.exceptions.BleScanException;
import com.polidea.rxohosble2.internal.RxBleLog;
import com.polidea.rxohosble2.internal.util.RxBleAdapterWrapper;
import com.polidea.rxohosble2.scan.BackgroundScanner;
import com.polidea.rxohosble2.scan.ScanFilter;
import com.polidea.rxohosble2.scan.ScanResult;
import com.polidea.rxohosble2.scan.ScanSettings;
import com.polidea.rxohosble2.annotation.NonNull;
import ohos.aafwk.content.Intent;
import ohos.bluetooth.ble.BleScanFilter;

import java.util.ArrayList;
import java.util.List;

public class BackgroundScannerImpl implements BackgroundScanner {

    private static final int NO_ERROR = 0;
    private final RxBleAdapterWrapper rxBleAdapterWrapper;
    private final OhosScanObjectsConverter scanObjectsConverter;
    private final InternalScanResultCreator internalScanResultCreator;
    private final InternalToExternalScanResultConverter internalToExternalScanResultConverter;

    @Inject
    BackgroundScannerImpl(RxBleAdapterWrapper rxBleAdapterWrapper,
                          OhosScanObjectsConverter scanObjectsConverter,
                          InternalScanResultCreator internalScanResultCreator,
                          InternalToExternalScanResultConverter internalToExternalScanResultConverter) {
        this.rxBleAdapterWrapper = rxBleAdapterWrapper;
        this.scanObjectsConverter = scanObjectsConverter;
        this.internalScanResultCreator = internalScanResultCreator;
        this.internalToExternalScanResultConverter = internalToExternalScanResultConverter;
    }

    @Override
    public void scanBleDeviceInBackground(@NonNull Intent callbackIntent, ScanSettings scanSettings, ScanFilter... scanFilters) {
        if (!rxBleAdapterWrapper.isBluetoothEnabled()) {
            RxBleLog.w("PendingIntent based scanning is available only when Bluetooth is ON.");
            throw new BleScanException(BleScanException.BLUETOOTH_DISABLED);
        }

        RxBleLog.i("Requesting pending intent based scan.");
        final List<BleScanFilter> nativeScanFilters = scanObjectsConverter.toNativeFilters(scanFilters);
        final RxBleAdapterWrapper.LeScanSetting nativeScanSettings = scanObjectsConverter.toNativeSettings(scanSettings);
        final int scanStartResult = rxBleAdapterWrapper.startLeScan(nativeScanFilters, nativeScanSettings, callbackIntent);

        if (scanStartResult != NO_ERROR) {
            final BleScanException bleScanException = new BleScanException(scanStartResult);
            RxBleLog.w(bleScanException, "Failed to start scan"); // TODO?
            throw bleScanException;
        }
    }

    @Override
    public void stopBackgroundBleScan(@NonNull Intent callbackIntent) {
        if (!rxBleAdapterWrapper.isBluetoothEnabled()) {
            RxBleLog.w("PendingIntent based scanning is available only when Bluetooth is ON.");
            return;
        }

        RxBleLog.i("Stopping pending intent based scan.");
        rxBleAdapterWrapper.stopLeScan(callbackIntent);
    }

    @Override
    public List<ScanResult> onScanResultReceived(@NonNull Intent intent) {
        final int callbackType = intent.getIntParam("EXTRA_CALLBACK_TYPE", -1);
        final int errorCode = intent.getIntParam("EXTRA_ERROR_CODE", NO_ERROR);
        final List<ScanResult> nativeScanResults = extractScanResults(intent);
        ArrayList<ScanResult> scanResults = new ArrayList<>();

        if (errorCode == NO_ERROR && nativeScanResults != null) {
//            for (ScanResult result : nativeScanResults) {
//                scanResults.add(convertScanResultToRxohosBLEModel(callbackType, result));
//            }
            for(ScanResult item : nativeScanResults) {
                scanResults.add(item);
            }

            return scanResults;
        } else {
            throw new BleScanException(errorCode);
        }
    }

    @SuppressWarnings("unchecked")
    private static List<ScanResult> extractScanResults(@NonNull Intent intent) {
        String[] result = intent.getStringArrayParam("EXTRA_LIST_SCAN_RESULT");
        ArrayList<ScanResult> scanResults = new ArrayList<>();

        if (scanResults != null) {
            for (String item : result) {
                scanResults.add(new ScanResult(item));
            }
        }
        return scanResults;
    }

    private ScanResult convertScanResultToRxohosBLEModel(int callbackType, ScanResult result) {
//        return internalToExternalScanResultConverter.apply(internalScanResultCreator.create(callbackType, result));
        return result;
    }
}
